//模型001 原理：Now-Low（20）/High(20)-Low（20）
package model

import (
	//"errors"
	//"fmt"
	. "git.oschina.net/OO-o/stock/base"
)

//数据的接口类型
type Dataer interface {
	ToData() *Data
}

//数据的基本类型
type Data struct {
	Code string
	Name string
	Date []string
	O    *Base
	C    *Base
	H    *Base
	L    *Base
}

//数据的返回信息
type Info struct {
	Code string
	Name string
	Data string
	Type string
}

func NewData(code string) *Data {
	var data *Data
	//Todo
	return data
}
func (d *Data) Check() bool {
	if d.C != nil && d.H != nil && d.L != nil && d.Date != nil {
		return true
	}
	return false
}

//在模型里这里的错误一定要检测，否则会报错！~

//模型001
func Model001(d Dataer, Nub int) []Info {
	var info []Info

	D := d.ToData()
	if !D.Check() {
		return info
	}
	//fmt.Println(D.Date)

	//fmt.Println("收盘价：", C)
	//fmt.Println("最高价：", H)
	//fmt.Println("最低价：", L)

	/*sub1 := Sub(D.C, LLV(D.L, 4))
	if len(HHV(H, 4).Value()) != len(LLV(L, 4).Value()) {
		fmt.Println(D.Code)
		fmt.Println("H len is", len(H.Value()))
		fmt.Println("L len is", len(L.Value()))
		fmt.Println("C is ", C.Value())
		fmt.Println("H is", H.Value())
		fmt.Println("L is", L.Value())
		fmt.Println("HHV(H, 4).Value() is", HHV(H, 4).Value())
		fmt.Println("LLV(L, 4).Value() is", LLV(L, 4).Value())

	}
	sub2 := Sub(HHV(D.H, 4), LLV(D.L, 4))
	if len(sub1.Value()) != len(sub2.Value()) {
		fmt.Println(D.Code)
		fmt.Println("HHV(H, 4)", len(HHV(H, 4).Value()))
		fmt.Println("LLV(L, 4)", len(LLV(L, 4).Value()))
		fmt.Println("C: ", len(C.Value()))
		fmt.Println("H:", len(H.Value()))
		fmt.Println("L:", len(L.Value()))
		fmt.Println("sub1:", len(sub1.Value()))
		fmt.Println("sub2:", len(sub2.Value()))
	}*/
	V3 := MulWithNub(Div(Sub(D.C, LLV(D.L, 4)), Sub(HHV(D.H, 4), LLV(D.L, 4))), 100)
	//	fmt.Println(V3.Value())
	V1 := SMA(V3, 2, 1)
	//	fmt.Println(V1.Value())
	V5 := SMA(V1, 2, 1)
	if V1 == nil {
		return info
	}
	for i := len(V1.Value()) - Nub; i < len(V1.Value()); i++ {
		//	fmt.Println("检测：", V1.I(i))
		if V1.I(i) > REF(V1, 1).I(i) && REF(V1, 1).I(i) < REF(V1, 2).I(i) && V1.I(i) < 23 {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "买入"
			info = append(info, item)
		}
		//	fmt.Println("检测", V1.I(i), "不符合！ 买入")
		if i-1 < 0 {
			continue
		}
		if V1.I(i) > REF(V1, 1).I(i) && (V1.I(i-1) <= V5.I(i-1) && V1.I(i) >= V5.I(i)) && V5.I(i) < 50 {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "追入"
			info = append(info, item)
		}
		//fmt.Println("检测", V1.I(i), "不符合！ 追入")
	}
	return info
}

func Model0011(d Dataer, Nub int) []Info {
	var info []Info

	D := d.ToData()
	//fmt.Println(D.Date)
	if !D.Check() {
		return info

	}
	//fmt.Println("收盘价：", C)
	//fmt.Println("最高价：", H)
	//fmt.Println("最低价：", L)

	V3 := MulWithNub(Div(Sub(D.C, LLV(D.L, 4)), Sub(HHV(D.H, 4), LLV(D.L, 4))), 100)
	//	fmt.Println(V3.Value())
	V1 := SMA(V3, 2, 1)
	//	fmt.Println(V1.Value())
	//fmt.Println(V1.Value())
	V5 := SMA(V1, 2, 1)
	if V1 == nil {
		return info
	}
	for i := len(V1.Value()) - Nub; i < len(V1.Value()); i++ {
		//	fmt.Println("检测：", V1.I(i))
		if V1.I(i) > REF(V1, 1).I(i) && REF(V1, 1).I(i) < REF(V1, 2).I(i) && V1.I(i) < 25 {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "买入"
			info = append(info, item)
		}
		//	fmt.Println("检测", V1.I(i), "不符合！ 买入")
		if i-1 < 0 {
			continue
		}
		if V1.I(i) > REF(V1, 1).I(i) && (V1.I(i-1) <= V5.I(i-1) && V1.I(i) >= V5.I(i)) && V5.I(i) < 50 {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "追入"
			info = append(info, item)
		}
		//fmt.Println("检测", V1.I(i), "不符合！ 追入")
	}
	return info
}

//模型002
//模型001+加入能量判断
func Model002(d Dataer, Nub int) []Info {
	var info []Info

	D := d.ToData()
	//fmt.Println(D.Date)
	if !D.Check() {
		return info
	}

	MAV := DivWithNub(Add(Add(MulWithNub(D.C, 3), D.H), D.L), 5)
	SK := Sub(EMA(MAV, 10), EMA(MAV, 20))
	SD := EMA(EMA(SK, 4), 4)
	SM := Sub(SK, SD)

	Liang := MulWithNub(Sub(SM, REF(SM, 1)), 10)
	V3 := MulWithNub(Div(Sub(D.C, LLV(D.L, 4)), Sub(HHV(D.H, 4), LLV(D.L, 4))), 100)
	//	fmt.Println(V3.Value())
	V1 := SMA(V3, 2, 1)
	//	fmt.Println(V1.Value())
	V5 := SMA(V1, 2, 1)
	if V1 == nil {
		return info
	}
	for i := len(V1.Value()) - Nub; i < len(V1.Value()); i++ {
		//	fmt.Println("检测：", V1.I(i))
		if i-2 < 0 {
			continue
		}
		if V1.I(i) > REF(V1, 1).I(i) && REF(V1, 1).I(i) < REF(V1, 2).I(i) && V1.I(i) < 23 && Liang.I(i) >= Liang.I(i-1) && Liang.I(i-1) > Liang.I(i-2) {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "买入"
			info = append(info, item)
		}
		//	fmt.Println("检测", V1.I(i), "不符合！ 买入")

		if V1.I(i) > REF(V1, 1).I(i) && (V1.I(i-1) <= V5.I(i-1) && V1.I(i) >= V5.I(i)) && V5.I(i) < 50 && Liang.I(i) >= Liang.I(i-1) && Liang.I(i-1) > Liang.I(i-2) {
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "追入"
			info = append(info, item)
		}
		//fmt.Println("检测", V1.I(i), "不符合！ 追入")
	}
	return info
}

//模型003
//模型002+趋势判断
func Model003(d Dataer, Nub int) []Info {
	var info []Info

	D := d.ToData()
	if !D.Check() {
		return info
	}

	//fmt.Println("收盘价：", C)
	//fmt.Println("最高价：", H)
	//fmt.Println("最低价：", L)

	MAV := DivWithNub(Add(Add(MulWithNub(D.C, 3), D.H), D.L), 5)
	SK := Sub(EMA(MAV, 10), EMA(MAV, 20))
	SD := EMA(EMA(SK, 4), 4)
	SM := Sub(SK, SD)

	Liliang := MulWithNub(Sub(SK, SD), 6)
	Liang := MulWithNub(Sub(SM, REF(SM, 1)), 10)
	V3 := MulWithNub(Div(Sub(D.C, LLV(D.L, 4)), Sub(HHV(D.H, 4), LLV(D.L, 4))), 100)
	//	fmt.Println(V3.Value())
	V1 := SMA(V3, 2, 1)
	//	fmt.Println(V1.Value())
	V5 := SMA(V1, 2, 1)
	if V1 == nil || len(V1.Value()) == 0 {
		return info
	}
	for i := len(V1.Value()) - Nub; i < len(V1.Value()); i++ {
		//	fmt.Println("检测：", V1.I(i))
		if i-2 < 0 {
			continue
		}
		if V1.I(i) > REF(V1, 1).I(i) && REF(V1, 1).I(i) < REF(V1, 2).I(i) && V1.I(i) < 23 && Liang.I(i) >= Liang.I(i-1) && Liang.I(i-1) > Liang.I(i-2) && Liliang.I(i) < 0 && D.Date[i][0:4] != "2014" {
			//fmt.Println(D.Code, "空乏力量：", Liliang.I(i))
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "买入"
			info = append(info, item)
		}
		//	fmt.Println("检测", V1.I(i), "不符合！ 买入")

		if V1.I(i) > REF(V1, 1).I(i) && (V1.I(i-1) <= V5.I(i-1) && V1.I(i) >= V5.I(i)) && V5.I(i) < 50 && Liang.I(i) >= Liang.I(i-1) && Liang.I(i-1) > Liang.I(i-2) && Liliang.I(i) < 0 && D.Date[i][0:4] != "2014" {
			//fmt.Println(D.Code, "空乏力量：", Liliang.I(i))
			var item Info
			item.Code = D.Code
			item.Name = D.Name
			item.Data = D.Date[i]
			item.Type = "追入"
			info = append(info, item)
		}
		//fmt.Println("检测", V1.I(i), "不符合！ 追入")
	}
	return info
}
